package com.xiaodai.miaosha.controller;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wf.captcha.ArithmeticCaptcha;
import com.xiaodai.miaosha.entity.SeckillOrder;
import com.xiaodai.miaosha.entity.Msuser;
import com.xiaodai.miaosha.rabbitmq.MQSender;
import com.xiaodai.miaosha.service.IGoodsService;
import com.xiaodai.miaosha.service.IMsuserService;
import com.xiaodai.miaosha.service.IOrdersService;
import com.xiaodai.miaosha.service.ISeckillOrderService;
import com.xiaodai.miaosha.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * *auther:xiaodai
 * *date:2022/3/207:12 PM
 * *describe:
 */
@Controller
@RequestMapping("/seckill")
@Slf4j
public class SeckillController implements InitializingBean {
    @Autowired
    private IGoodsService goodsService;
    @Autowired
    private IMsuserService userService;
    @Autowired
    private ISeckillOrderService seckillOrderService;
    @Autowired
    private IOrdersService orderService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private MQSender mqSender;
    @Autowired
    private RedisScript<Long> redisScript;

    private Map<Long, Boolean> EmptyStockMap = new HashMap<>();

    @GetMapping("/getResult")
    @ResponseBody
    public RespBean getResult(@CookieValue("userTicket") String ticket, HttpServletRequest request, HttpServletResponse response,Long goodsId,String addressId){
        Msuser Msuser = userService.getUserByCookie(ticket,request,response);
        if (Msuser == null){
            return RespBean.error(RespBeanEnum.SESSION_ERROR);
        }
        Long result = orderService.getResult(Msuser,goodsId,addressId);
        System.out.println(result);
        return RespBean.success(result);
    }

    @PostMapping("/{path}/doSeckill")
    @ResponseBody
    public RespBean doSeckill(@CookieValue("userTicket") String ticket, HttpServletRequest request, HttpServletResponse response, Long goodsId,@PathVariable("path") String path,String addressId){

        System.out.println(addressId);
        Msuser Msuser = userService.getUserByCookie(ticket,request,response);
        if (Msuser == null){
            return RespBean.error(RespBeanEnum.SESSION_ERROR);
        }

        ValueOperations valueOperations = redisTemplate.opsForValue();

        Boolean flag = orderService.checkPath(Msuser,goodsId,path);
        if (!flag){
            return RespBean.error(RespBeanEnum.REQUEST_ILLEGAL);
        }

        GoodsVo goodsVoById = goodsService.findGoodsVoById(goodsId);
        int count = seckillOrderService.count(new QueryWrapper<SeckillOrder>().eq("user_id", Msuser.getId()).eq("goods_id", goodsId));
        System.out.println(count);
        if (count >= goodsVoById.getLimitCount()){
            return RespBean.error(RespBeanEnum.REPEATE_ERROR);
        }
        System.out.println(goodsId);
        if (EmptyStockMap.get(goodsId)){
            return RespBean.error(RespBeanEnum.EMPTY_STOCK);
        }
//        Long stock = valueOperations.decrement("seckillGoods:" + goodsId);
        Long stock = (Long)redisTemplate.execute(redisScript, Collections.singletonList("seckillGoods:" + goodsId), Collections.EMPTY_LIST);
        if (stock < 0 ){
            EmptyStockMap.put(goodsId,true);
            valueOperations.increment("seckillGoods:"+goodsId);
            return RespBean.error(RespBeanEnum.EMPTY_STOCK);
        }
        SeckillMessage seckillMessage = new SeckillMessage(Msuser, goodsId,addressId);
        mqSender.sendSeckillMessage(JSON.toJSONString(seckillMessage));
        return RespBean.success(0);
    }

    @GetMapping("/path")
    @ResponseBody
    public RespBean getPath(@CookieValue("userTicket") String ticket, HttpServletRequest request,HttpServletResponse response,Long goodsId,String captcha){
        Msuser Msuser = userService.getUserByCookie(ticket,request,response);
        if (Msuser == null){
            return RespBean.error(RespBeanEnum.SESSION_ERROR);
        }
        Boolean flag = orderService.checkCaptcha(Msuser, goodsId, captcha);
        if (!flag) {
            return RespBean.error(RespBeanEnum.ERROR_CAPTCHA);
        }
        String path = orderService.getPath(Msuser, goodsId);
        return RespBean.success(path);
    }

    @GetMapping("/captcha")
    public void getCaptcha(@CookieValue("userTicket") String ticket, HttpServletRequest request,HttpServletResponse response,Long goodsId){
        Msuser Msuser = userService.getUserByCookie(ticket,request,response);
        if (Msuser == null){
            return;
        }
        response.setContentType("image/jpg");
        response.setHeader("Pargam", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        ArithmeticCaptcha captcha = new ArithmeticCaptcha(130, 32, 3);
        redisTemplate.opsForValue().set("captcha:" + Msuser.getId() + ":" + goodsId, captcha.text(), 300, TimeUnit.HOURS);
        try {
            captcha.out(response.getOutputStream());
        } catch (IOException e) {
            log.error("验证码生成失败", e.getMessage());
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("系统初始化");
        List<GoodsVo> goodsVo = goodsService.findGoodsVo();
        if (goodsVo.isEmpty()){
            return;
        }
        goodsVo.forEach(a->{redisTemplate.opsForValue().set("seckillGoods:"+a.getId(),a.getStockCount());
                        EmptyStockMap.put(a.getId(),false);
        });
    }
}
